import { gradualColorRampList } from '#/assets/style';
import { getColorArray } from '#/utils';

class HierarchicalRender {
  constructor(map) {
    this.map = map;
    this.colorRampList = gradualColorRampList;
  }

  getBreakPointArr(uniqueValues, level) {
    const perNum = Number.parseInt(uniqueValues.length / level);
    let remain = uniqueValues.length % level;
    const breakPointArr = [];
    const tempArr = [];
    for (let i = 1; i <= level; i++) {
      if (remain > 0) {
        tempArr.push(perNum + 1);
        remain--;
      } else {
        tempArr.push(perNum);
      }
    }
    // console.log(tempArr)
    let index = 0;
    for (let i = 0; i < tempArr.length - 1; i++) {
      index += tempArr[i];
      breakPointArr.push(uniqueValues[index]);
    }
    // console.log(breakPointArr)
    return breakPointArr;
  }

  getBreakPointArr2(uniqueValues, level) {
    const perNum = Number.parseInt(uniqueValues.length / level);
    let remain = uniqueValues.length % level;
    const breakPointArr = [];
    const tempArr = [];
    for (let i = 1; i <= level; i++) {
      if (remain > 0) {
        tempArr.push(perNum + 1);
        remain--;
      } else {
        tempArr.push(perNum);
      }
    }
    // console.log(tempArr)
    let index = 0;
    breakPointArr.push(index);
    for (const element of tempArr) {
      index += element;
      breakPointArr.push(index);
    }
    // console.log(breakPointArr)
    return breakPointArr;
  }
  getCircleRadiusArr(circleRadiusRange, level) {
    const circleRadiusArr = [];
    const perNum = Number.parseFloat(
      ((circleRadiusRange[1] - circleRadiusRange[0]) / (level - 1)).toFixed(2),
    );
    for (let i = 0; i < level - 1; i++) {
      circleRadiusArr.push(circleRadiusRange[0] + i * perNum);
    }
    circleRadiusArr.push(circleRadiusRange[1]);
    // console.log(circleRadiusArr)
    return circleRadiusArr;
  }

  getColorRampArray(colorRampName, level) {
    const gradualRamp = this.colorRampList.find(
      (ramp) => ramp.name === colorRampName,
    ).ramp;
    return getColorArray(gradualRamp, level);
  }
  getRandomColor() {
    return `#${Math.random().toString(16).slice(2, 8)}`;
  }

  hierarchicalRenderEntry(options) {
    switch (options.layerType) {
      case 'circle': {
        return this.pointHierarchicalRender(options);
      }
      case 'fill': {
        return this.polygonHierarchicalRender(options);
      }
      case 'line': {
        return this.polylineHierarchicalRender(options);
      }
    }
  }

  /**
   * Renders color for a hierarchical circle based on given options.
   *
   * @param {object} options - An object that contains render options.
   * @param {string} options.layerId - The ID of the layer.
   * @param {string} options.renderField - The field to be rendered.
   * @param {Array} options.uniqueValues - The unique values of the field.
   * @param {string} options.colorRamp - The color ramp used for rendering.
   * @param {number} options.level - The level of the rendering.
   * @param {object} options.layerOptions - The options of the layer.
   * @param {object} options.layerOptions.layout - The layout options of the layer.
   * @param {object} options.layerOptions.paint - The paint options of the layer.
   *
   * @return {void}
   */
  // pointHierarchicalCircleColorRender(options) {
  //   const { layerId, renderField, uniqueValues, colorRamp, level, layerOptions } = options
  //   const layout = layerOptions.layout
  //   const paint = layerOptions.paint
  //   const colorRampArray = this.getColorRampArray(colorRamp, level)
  //   const paintExpressionArr = new Array()
  //   const breakPoinIndextArr = this.getBreakPointArr2(uniqueValues, level)
  //   console.log(breakPoinIndextArr)
  //   paintExpressionArr.push('case')
  //   // paintExpressionArr.push(['get', renderField])
  //   for (let i = 0; i < breakPoinIndextArr.length - 1; i++) {
  //     for (let j = breakPoinIndextArr[i]; j < breakPoinIndextArr[i + 1]; j++) {
  //       // paintExpressionArr.push([uniqueValues[j], colorRampArray[i]])
  //       paintExpressionArr.push(['==', ['get', renderField], uniqueValues[j]])
  //       paintExpressionArr.push(colorRampArray[i])
  //     }
  //   }
  //   paintExpressionArr.push('#000000')
  //   console.log(paintExpressionArr)
  //   Object.keys(layout).forEach(key => {
  //     this.map.setLayoutProperty(layerId, key, layout[key])
  //   })
  //   Object.keys(paint).forEach(key => {
  //     this.map.setPaintProperty(layerId, key, paint[key])
  //   })
  //   this.map.setPaintProperty(layerId, 'circle-color', paintExpressionArr)
  // }
  pointHierarchicalCircleColorRender(options) {
    const {
      layerId,
      renderField,
      uniqueValues,
      colorRamp,
      level,
      layout,
      paint,
    } = options;
    const colorRampArray = this.getColorRampArray(colorRamp, level);
    const paintExpressionArr = [];
    const breakPoinIndextArr = this.getBreakPointArr2(uniqueValues, level);
    // console.log(breakPoinIndextArr);
    paintExpressionArr.push('case');
    // paintExpressionArr.push(['get', renderField])
    for (let i = 0; i < breakPoinIndextArr.length - 1; i++) {
      for (let j = breakPoinIndextArr[i]; j < breakPoinIndextArr[i + 1]; j++) {
        // paintExpressionArr.push([uniqueValues[j], colorRampArray[i]])
        paintExpressionArr.push(
          ['==', ['get', renderField], uniqueValues[j]],
          colorRampArray[i],
        );
      }
    }
    paintExpressionArr.push('#000000');
    // console.log(paintExpressionArr)
    // 清空原先的图层属性
    const paintProps = this.map.getLayer(layerId).paint;
    Object.keys(paintProps).forEach((key) => {
      this.map.setPaintProperty(layerId, key, null);
    });
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'circle-color', paintExpressionArr);
  }

  pointHierarchicalCircleRadiusRender(options) {
    const {
      layerId,
      renderField,
      uniqueValues,
      circleRadiusRange,
      level,
      layout,
      paint,
    } = options;
    const circleRadiusArr = this.getCircleRadiusArr(circleRadiusRange, level);
    const paintExpressionArr = [];
    const breakPoinIndextArr = this.getBreakPointArr2(uniqueValues, level);
    paintExpressionArr.push('case');
    for (let i = 0; i < breakPoinIndextArr.length - 1; i++) {
      for (let j = breakPoinIndextArr[i]; j < breakPoinIndextArr[i + 1]; j++) {
        paintExpressionArr.push(
          ['==', ['get', renderField], uniqueValues[j]],
          circleRadiusArr[i],
        );
      }
    }
    paintExpressionArr.push(1);
    // console.log(paintExpressionArr)
    // 清空原先的图层属性
    const paintProps = this.map.getLayer(layerId).paint;
    Object.keys(paintProps).forEach((key) => {
      this.map.setPaintProperty(layerId, key, null);
    });
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'circle-radius', paintExpressionArr);
  }

  pointHierarchicalRender(options) {
    if (options.hierarchicalMethod === 'hierarchical_color') {
      this.pointHierarchicalCircleColorRender(options);
    } else {
      this.pointHierarchicalCircleRadiusRender(options);
    }
  }

  polygonHierarchicalRender(options) {
    const {
      layerId,
      renderField,
      uniqueValues,
      level,
      colorRamp,
      layout,
      paint,
    } = options;
    const colorRampArray = this.getColorRampArray(colorRamp, level);
    const paintExpressionArr = [];
    if (uniqueValues.length <= level) {
      paintExpressionArr.push('case');
      // paintExpressionArr.push(['get', renderField])
      for (const [i, uniqueValue] of uniqueValues.entries()) {
        paintExpressionArr.push(
          ['==', ['get', renderField], uniqueValue],
          colorRampArray[i],
        );
      }
      paintExpressionArr.push('#000000');
    } else {
      const breakPointArr = this.getBreakPointArr(uniqueValues, level);
      paintExpressionArr.push('case');
      // paintExpressionArr.push(['get', renderField])
      for (let i = 0; i < level - 1; i++) {
        paintExpressionArr.push(
          ['<', ['get', renderField], breakPointArr[i]],
          colorRampArray[i],
        );
      }
      paintExpressionArr.push(
        ['<=', ['get', renderField], uniqueValues[uniqueValues.length - 1]],
        colorRampArray[level - 1],
        '#000000',
      );
    }
    // console.log(paintExpressionArr)s
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'fill-color', paintExpressionArr);
  }
  polylineHierarchicalColorRender(options) {
    const {
      layerId,
      renderField,
      uniqueValues,
      colorRamp,
      level,
      layout,
      paint,
    } = options;
    const colorRampArray = this.getColorRampArray(colorRamp, level);
    const paintExpressionArr = [];
    // const breakPointArr = this.getBreakPointArr(uniqueValues, level);
    const breakPoinIndextArr = this.getBreakPointArr2(uniqueValues, level);
    // console.log(breakPoinIndextArr);
    paintExpressionArr.push('case');
    // paintExpressionArr.push(['get', renderField])
    for (let i = 0; i < breakPoinIndextArr.length - 1; i++) {
      for (let j = breakPoinIndextArr[i]; j < breakPoinIndextArr[i + 1]; j++) {
        // paintExpressionArr.push([uniqueValues[j], colorRampArray[i]])
        paintExpressionArr.push(
          ['==', ['get', renderField], uniqueValues[j]],
          colorRampArray[i],
        );
      }
    }
    paintExpressionArr.push('#000000');
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'line-color', paintExpressionArr);
  }

  polylineHierarchicalLineWidthRender(options) {
    const {
      layerId,
      renderField,
      uniqueValues,
      lineWidthRange,
      level,
      layout,
      paint,
    } = options;
    const lineWidthArr = this.getCircleRadiusArr(lineWidthRange, level);
    const paintExpressionArr = [];
    const breakPoinIndextArr = this.getBreakPointArr2(uniqueValues, level);
    paintExpressionArr.push('case');
    for (let i = 0; i < breakPoinIndextArr.length - 1; i++) {
      for (let j = breakPoinIndextArr[i]; j < breakPoinIndextArr[i + 1]; j++) {
        paintExpressionArr.push(
          ['==', ['get', renderField], uniqueValues[j]],
          lineWidthArr[i],
        );
      }
    }
    paintExpressionArr.push(1);
    // console.log(paintExpressionArr)
    Object.keys(layout).forEach((key) => {
      this.map.setLayoutProperty(layerId, key, layout[key]);
    });
    Object.keys(paint).forEach((key) => {
      this.map.setPaintProperty(layerId, key, paint[key]);
    });
    this.map.setPaintProperty(layerId, 'line-width', paintExpressionArr);
  }
  polylineHierarchicalRender(options) {
    if (options.hierarchicalMethod === 'hierarchical_color') {
      this.polylineHierarchicalColorRender(options);
    } else {
      this.polylineHierarchicalLineWidthRender(options);
    }
  }
}

// const fj = new HierarchicalRender()
// const arr = [1, 3, 4, 5, 6, 7, 8, 9, 10]
// const arr = ['w', 'j', 'r']
// console.log(fj.getCircleRadiusArr([1, 10], 5));
// console.log(fj.getBreakPointArr(arr, 4));
export default HierarchicalRender;
